`timescale 1ns/100ps
`default_nettype none

/******************** 
 * Interpolation
 ********************/
module Interpolation (
    input logic CLOCK_50_I,                 // 50 MHz clock
    input logic resetn,                     // Reset

    input logic [7:0] R[5:0],
    input logic start,                      // Start interpolation

    // Multiplier
    input logic [31:0] mulResult,           // Result of multiplier
    output logic [31:0] mulOp1,             // Op1 to multiplier
    output logic [31:0] mulOp2,             // Op2 to multiplier

    output logic [31:0] intResult,          // Interpolated result
    output logic finish                     // Indicate we are done
);

enum logic [2:0] {
    S0,
    S1,
    S2,
    S3
} state;

logic [31:0] acc;       // Accumulator

// Chop off the result by 256
assign intResult = (acc[31]==1)?32'b0:(|acc[30:16])?32'd255:{8'b0, acc[31:8]};

always_ff @ (posedge CLOCK_50_I or negedge resetn) begin
    if (resetn == 1'b0) begin
        acc <= 32'd128;         // Pre load accumulator with 128
        finish <= 1'b0;
        state <= S0;
    end else begin
        case (state)
        S0: begin
            if (start) begin
                state <= S1;
                acc <= 32'd128;
                finish <= 1'b0;
            end
        end
        S1: begin
            acc <= acc + mulResult; // acc+=21*{ R[0]+R[5] }
            state <= S2;
        end
        S2: begin
            acc <= acc - mulResult; // acc-=59*{ R[1]+R[4] }
            state <= S3;
        end
        S3: begin
            acc <= acc + mulResult; // acc+=152*{ R[2]+R[3] }
            finish <= 1'b1;
            state <= S0;
        end
        default: state <= S0;
        endcase
    end
end

/********************************
 * Multiplication block
 ********************************/
always_comb begin
    case(state)
    S0: begin
        mulOp1 = 32'b0;
        mulOp2 = 32'b0;
    end
    S1: begin
        // mulResult = 21*{ R[0]+R[5] }
        mulOp1 = 32'd21;
        mulOp2 = R[0]+R[5];
    end
    S2: begin
        // mulResult = 52*{ R[1]+R[4] }
        mulOp1 = 32'd52;
        mulOp2 = R[1]+R[4];
    end
    S3: begin
        // mulResult = 159*{ R[2]+R[3] }
        mulOp1 = 32'd159;
        mulOp2 = R[2]+R[3];
    end
    default: begin
        mulOp1 = 32'b0;
        mulOp2 = 32'b0;
    end
    endcase
end

endmodule
